package com.qlogic.commons.platform.impls.lucene.handler;

import java.io.InputStream;

import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.w3c.tidy.Tidy;

public class TidyHtmlHandler implements ContentHandler {
	
	protected Tidy tidy;
	protected Element rawDoc; 
	
	public TidyHtmlHandler () {
		Tidy tidy = new Tidy();
		tidy.setQuiet(true);
		tidy.setShowWarnings(false);
	}
	
	protected void parseDocument (InputStream is, String encoding) {
		org.w3c.dom.Document root = tidy.parseDOM(is, null);
		rawDoc = root.getDocumentElement();
	}

	public Document getDocument(InputStream is, String encoding) throws ContentHandlerException {
		if (rawDoc == null) {
			parseDocument (is, encoding);
		}
		Document doc = new Document();
		String title = getTitle(rawDoc);
		if ((title != null) && (!title.equals(""))) {
			doc.add(new Field(TITLE, title, Field.Store.YES,
					Field.Index.TOKENIZED));
		}
		String body = getText(is, encoding);
		if ((body != null) && (!body.equals(""))) {
			doc.add(new Field(BODY, body, Field.Store.YES,
					Field.Index.TOKENIZED));
		}

		return doc;
	}

	protected String getTitle(Element rawDoc) {
		if (rawDoc == null) {
			return null;
		}

		String title = "";

		NodeList children = rawDoc.getElementsByTagName("title");
		if (children.getLength() > 0) {
			Element titleElement = ((Element) children.item(0));
			Text text = (Text) titleElement.getFirstChild();
			if (text != null) {
				title = text.getData();
			}
		}
		return title;
	}

	protected String getBody(Element rawDoc) {
		if (rawDoc == null) {
			return null;
		}

		String body = "";
		NodeList children = rawDoc.getElementsByTagName("body");
		if (children.getLength() > 0) {
			body = getText(children.item(0));
		}
		return body;
	}

	protected String getText(Node node) {
		NodeList children = node.getChildNodes();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < children.getLength(); i++) {
			Node child = children.item(i);
			switch (child.getNodeType()) {
			case Node.ELEMENT_NODE:
				sb.append(getText(child));
				sb.append(" ");
				break;
			case Node.TEXT_NODE:
				sb.append(((Text) child).getData());
				break;
			}
		}
		return sb.toString();
	}

	public String getText(InputStream is, String encoding)
			throws ContentHandlerException {
		if (rawDoc == null) {
			parseDocument (is, encoding);
		}
		return getBody(rawDoc);
	}

}
